/*
 * @Description: 
 * @Author: YangHeng
 * @Date: 2021-08-10 19:59:16
 * @FilePath: \web_server_app\mongoose\model.js
 */

const mongoose = require('mongoose');
const {extendClassMethods} = require('./util');
const Socket = require('./socket')
const StaticDb = require('./static')
const { isObject } = require('core-util-is')
const defaultOptions = require('./default')

// 创建唯一标识方式模型重复
const MODELS = Symbol('mongoose-models');
const models = {}; // 存储全局模型实例


class Mongoose extends StaticDb {
  /**
   * @description: 数据库实例
   * @param {*} modelName 模型名称
   */
  constructor(modelName) {
    super();
    let name = modelName
    let config = civi.config.mongo
    this.modelName = modelName;
    this.config = config;
    if (models[name]) return models[name]; // 已存在实例直接返回

    // 获取连接实例
    const connection = Socket.create();
    const schema = this.schema;
    if (schema instanceof mongoose.Schema) {
      // 添加公共字段
      schema.add(new mongoose.Schema(civi.config.mongo.commonField || {}));

      // 绑定预处理方法
      if (isObject(civi.config.mongo.pre)) {
        Object.keys(civi.config.mongo.pre).forEach(item => {
          schema.pre(item, civi.config.mongo.pre[item]);
        })
      }
    } else throw Error('Please pass in the mongoose.Schema type instance');

    const model = connection.model(this.tableName, schema, config.useCollectionPlural ? null : this.tableName);
    this.modelClass = class extends model {}
    extendClassMethods(this.modelClass, this);
    models[name] = this.modelClass;
    return this.modelClass;
  }
  static get isModel () {return true}
  static getModels (name) {
    if (models[name]) return models[name]; // 已存在实例直接返回
    let model = new this(name)
    return model
  }
  // 表前缀
  get tablePrefix() {
    return this.config.prefix || '';
  }
  // 表名
  get tableName() {
    return this.tablePrefix + this.modelName;
  }
  // 获取模型
  get models() {
    return this[MODELS] || {};
  }
  // 设置模型
  set models(value) {
    this[MODELS] = value;
  }
}

// 挂在类的静态对象
Mongoose.mongoose = mongoose;
Mongoose.Schema = mongoose.Schema;
Mongoose.Mixed = mongoose.Schema.Types.Mixed;
Mongoose.ObjId = mongoose.Schema.Types.ObjectId;

module.exports = Mongoose;